package com.fshows.leshuapay.sdk.client.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fshows.leshuapay.sdk.client.LeshuaRiskClient;
import com.fshows.leshuapay.sdk.enums.RiskApiEnum;
import com.fshows.leshuapay.sdk.exception.LeshuaException;
import com.fshows.leshuapay.sdk.request.LeshuaBizRequest;
import com.fshows.leshuapay.sdk.response.LeshuaBaseResponse;
import com.fshows.leshuapay.sdk.util.LeshuaSignature;
import com.fshows.leshuapay.sdk.util.ReqSerialNoUtil;
import com.fshows.leshuapay.sdk.util.SignUtil;
import com.fshows.leshuapay.sdk.util.ValidateUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Scanner;

/**
 * @author cll
 * @version LeshuaRiskClientImpl.java, v 0.1 2021-08-12 11:20 cll
 */
@Slf4j
@Data
public class LeshuaRiskClientImpl implements LeshuaRiskClient {

    /**
     * 从connectManager获取Connection 超时时间
     */
    private static final int CONNECTION_REQUEST_TIMEOUT = 5000;

    /**
     * 读取数据的超时时间
     */
    private static final int SOCKET_TIMEOUT = 10000;

    /**
     * 连接超时时间
     */
    private static final int CONNECT_TIMEOUT = 6000;

    /**
     * 版本号
     */
    private static final String VERSION = "1.0";

    /**
     * 商户服务地址
     */
    private String serverUrl;

    /**
     * 服务商编号
     */
    private String agentId;

    /**
     * 服务商私钥
     */
    private String privateKey;

    /**
     * 请求超时时间，单位毫秒
     */
    private Integer timeout;

    /**
     * @param serverUrl  商户地址
     * @param agentId    服务商编号
     * @param privateKey 服务商私钥
     * @param timeout    毫秒
     */
    public LeshuaRiskClientImpl(
            String serverUrl, String agentId, String privateKey, Integer timeout) {
        this.serverUrl = serverUrl;
        this.agentId = agentId;
        this.privateKey = privateKey;
        this.timeout = timeout;
    }

    @Override
    public <T> LeshuaBaseResponse<T> execute(
            LeshuaBizRequest<T> request, RiskApiEnum riskApiEnum, String url, Integer timeout)
            throws LeshuaException {
        ValidateUtil.validateWithThrow(request);
        RequestConfig requestConfig = null;
        if (timeout == null || timeout <= 0) {
            requestConfig = RequestConfig.custom().setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT)
                    .setSocketTimeout(SOCKET_TIMEOUT).setConnectTimeout(CONNECT_TIMEOUT).build();
        } else {
            requestConfig = RequestConfig.custom().setConnectionRequestTimeout(timeout)
                    .setSocketTimeout(timeout).setConnectTimeout(timeout).build();
        }
        // 要调用的接口方法
        HttpPost httpPost = new HttpPost(serverUrl + url);
        httpPost.setConfig(requestConfig);
        // 根据不同的url获取不同的签名值
        request = riskApiEnum.getRiskApiSign().doSign(request, privateKey, agentId);
        StringEntity stringEntity =
                new StringEntity(JSON.toJSONString(request), ContentType.APPLICATION_JSON);
        httpPost.setEntity(stringEntity);
        CloseableHttpResponse httpResponse = null;
        HttpEntity resEntity = null;
        CloseableHttpClient httpClient = null;
        try {
            httpClient = HttpClients.createDefault();
            log.info("请求乐刷接口入参:{}", JSON.toJSONString(request));
            httpResponse = httpClient.execute(httpPost);
            resEntity = httpResponse.getEntity();
            String responseStr = EntityUtils.toString(resEntity, SignUtil.DEFAULT_CHARSET);
            LeshuaBaseResponse<T> response = new LeshuaBaseResponse<>();
            JSONObject jsonObject = JSON.parseObject(responseStr);
            response.setRespCode(jsonObject.getString("error_code"));
            response.setRespMsg(jsonObject.getString("error_msg"));
            String data = jsonObject.getString("data");
            if (StringUtils.isNotEmpty(data)) {
                response.setData(JSON.parseObject(data, request.getResponseClass()));
            }
            log.info("请求乐刷接口入参:{} 请求乐刷接口返回参数:{}", JSON.toJSONString(request), response);
            return response;
        } catch (Exception e) {
            throw new LeshuaException("调用失败", e);
        } finally {
            try {
                EntityUtils.consume(resEntity);
            } catch (IOException e) {
                log.error("释放HttpEntity出错，错误信息：" + e.getMessage(), e);
            }
            if (httpResponse != null) {
                try {
                    httpResponse.close();
                } catch (IOException e) {
                    log.error("关闭HttpResponse出错，错误信息：" + e.getMessage(), e);
                }
            }
        }
    }

    public static void main(String[] args) {
        //先插入末尾然后循环排序
        String[] music = {"Island", "Ocean", "Pretty", "Sun", ""};
        Scanner input = new Scanner(System.in);
        music[music.length - 1] = input.next();
        Arrays.sort(music);
        //
        System.out.println(JSON.toJSONString(music));
    }

    @Override
    public <T> LeshuaBaseResponse<T> executeHttp(LeshuaBizRequest<T> request, String url) throws LeshuaException {
        ValidateUtil.validateWithThrow(request);
        log.info("乐刷请求，request={}", JSON.toJSONString(request));
        //组装HttpPost对象
        HttpPost httppost = buildHttpPost(JSON.toJSONString(request), url);
        CloseableHttpResponse httpResponse = null;
        HttpEntity resEntity = null;
        log.info("乐刷请求，httppost={}", JSON.toJSONString(httppost));
        CloseableHttpClient httpClient = null;
        try {
            httpClient = HttpClients.createDefault();
            httpResponse = httpClient.execute(httppost);
            resEntity = httpResponse.getEntity();
            String responseStr = EntityUtils.toString(resEntity, SignUtil.DEFAULT_CHARSET);
            log.info("乐刷返回，response={}", responseStr);
            LeshuaBaseResponse<T> response = new LeshuaBaseResponse<>();
            JSONObject jsonObject = JSON.parseObject(responseStr);
            response.setReqSerialNo(jsonObject.getString("reqSerialNo"));
            response.setRespCode(jsonObject.getString("respCode"));
            response.setRespMsg(jsonObject.getString("respMsg"));
            if (!StringUtils.isBlank(jsonObject.getString("data"))) {
                response.setData(JSON.parseObject(jsonObject.getString("data"), request.getResponseClass()));
            }
            return response;
        } catch (Exception e) {
            log.error("调用乐刷接口异常 error:{}", e);
            throw new LeshuaException("调用失败", e);
        } finally {
            try {
                EntityUtils.consume(resEntity);
            } catch (IOException e) {
                log.error("释放HttpEntity出错，错误信息：" + e.getMessage(), e);
            }
            if (httpResponse != null) {
                try {
                    httpResponse.close();
                } catch (IOException e) {
                    log.error("关闭HttpResponse出错，错误信息：" + e.getMessage(), e);
                }
            }
        }
    }

    private HttpPost buildHttpPost(String request, String url) throws LeshuaException {
        //请求流水号
        String reqSerialNo = ReqSerialNoUtil.getReqSerialNo();
        //获取签名
        String sign = LeshuaSignature.getRiskBase64Sign(privateKey, request);
        RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT)
                .setSocketTimeout(SOCKET_TIMEOUT).setConnectTimeout(CONNECT_TIMEOUT).build();
        //构建对象
        HttpPost httppost = new HttpPost(serverUrl + url);
        httppost.setConfig(requestConfig);
        MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
        multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
        multipartEntityBuilder.setCharset(Charset.forName(SignUtil.DEFAULT_CHARSET));
        //代理商编号
        multipartEntityBuilder.addPart("agentId", new StringBody(agentId, ContentType.APPLICATION_JSON));
        //版本
        multipartEntityBuilder.addPart("version", new StringBody(VERSION, ContentType.APPLICATION_JSON));
        //请求流水号
        multipartEntityBuilder.addPart("reqSerialNo", new StringBody(reqSerialNo, ContentType.APPLICATION_JSON));
        //数据内容
        multipartEntityBuilder.addPart("data", new StringBody(request, ContentType.APPLICATION_JSON));
        //签名值
        multipartEntityBuilder.addPart("sign", new StringBody(sign, ContentType.APPLICATION_JSON));
        HttpEntity reqEntity = multipartEntityBuilder.build();
        httppost.setEntity(reqEntity);
        return httppost;
    }
}
